home *** CD-ROM | disk | FTP | other *** search
- {program DB_FILES
- This is one of a series of utilities intended for analyzing dBASE III .PRG
- files. This program prints out the structure of all .DBF files, and the
- keys of the associated .ndx files, used in each .PRG of any given tree.
-
- Written by Curtis H. Hoffmann
-
- version A1 11/05/86
-
- A1 11/05/86 Initial Release
-
- }
-
-
- const
- blanks= ' ';
-
- type
- name = string[12];
- stt = string[255];
- datetype = string[8];
- regtype = record
- ax,bx,cx,dx,bp,si,di,ds,es,flags: integer
- end;
-
- var
- file_in, file_out : text;
- all_files, abo : char;
- in_file, ofl : string[8];
- out_file : string[12];
- mac_name : string[13];
- progs, dbf, ndx : array[1..100] of string[12];
- macro : array[1..100] of string[15];
- mac_var : array[1..100] of string[10];
- ndx_stack : array[1..100] of integer;
- dbf_to_ndx : array[1..100] of integer;
- sele_stack : array[1..10] of integer;
- prog_stack, line_stack : array[1..20] of integer;
- ps, sp, ln_cnt, dp, np, d_p, sx, mp : integer;
- st, outstring, temp_st, path : string[255];
- next_word, this_word : string[10];
- more_words, skip_line, pass_one, a_d : boolean;
-
-
- function time: datetype;
- var reg: regtype;
- h,m,s,w: datetype;
- i: integer;
-
- begin
- reg.ax:=$2c00;
- intr($21,reg);
- str(hi(reg.cx):2,h);
- str(lo(reg.cx):2,m);
- str(hi(reg.dx):2,s);
- w:=h+':'+m+':'+s;
- for i:=1 to length(w) do if w[i]=' ' then w[i]:='0';
- time:=w;
- end;
-
- function date: datetype;
- var reg: regtype;
- y,m,d,w: datetype;
- i: integer;
-
- begin
- reg.ax:=$2a00;
- intr($21,reg);
- str(reg.cx:4,y);
- delete(y,1,2);
- str(hi(reg.dx):2,m);
- str(lo(reg.dx):2,d);
- w:=m+'/'+d+'/'+y;
- for i:=1 to length(w) do if w[i]=' ' then w[i]:='0';
- date:=w;
- end;
-
- function exist(filename: name): boolean; {Do requested files exist?}
- var fil: file;
- begin
- assign(fil, filename);
- {$I-}
- reset(fil);
- {$I+}
- exist:=(IOresult=0);
- close(fil);
- end;
-
- function standard_io(h :name): boolean; {Is requested file PRN or CON?}
- begin
- if ((h='prn') or (h='PRN')) or ((h='con') or (h='CON')) then
- standard_io:=true
- else standard_io:=false;
- end;
-
- procedure get_started; {Request I/O files, open them}
- var ow: char;
- j: integer;
- begin
- abo:='N'; clrscr; gotoxy(10,10);
- write('Input .PRG file to check first : '); read(in_file); gotoxy(10,12);
- write('File to dump output to (prn for printer): '); read(out_file); gotoxy(10,14);
- write('Check all files, or just this one (A/O) : '); readln(all_files);
- all_files:=upcase(all_files);
- if not exist(in_file+'.prg') then begin
- writeln(in_file+'.PRG does not exist, program aborted'); abo:='Y'; end
- else begin
- for j:=1 to length(in_file) do
- if (in_file[j]>='a') and (in_file[j]<='z') then
- in_file[j]:=upcase(in_file[j]);
- assign(file_in, in_file+'.prg'); reset(file_in);
- end;
- textcolor(12);
- if not standard_io(out_file) then if exist(out_file) then begin
- write(out_file+' exists, overwrite it (Y/N)?: '); readln(ow);
- if upcase(ow)<>'Y' then begin write('Program aborted'); abo:='Y'; end;
- end;
- textcolor(14);
- progs[1]:=in_file;
- if abo<>'Y' then begin assign(file_out, out_file); rewrite(file_out); end;
- end;
-
- procedure init; {Initialize variables}
- var i: integer;
- begin
- ln_cnt:=0; dp:=0; getdir(0,path); np:=0; mp:=0;
- sp:=1; ps:=1; prog_stack[sp]:=1; sx:=1;
- for i:=1 to 20 do line_stack[i]:=0;
- end;
-
- procedure push_stack; {Put current .PRG in stack,}
- var y: integer; {print out filename, variable list}
- v: boolean; {then open next called filename}
- begin
- line_stack[ps]:=ln_cnt; ps:=ps+1; y:=1;
- while (y<=sp) and (next_word<>progs[y]) do y:=y+1;
- if y>sp then begin sp:=sp+1; progs[sp]:=next_word; end;
- prog_stack[ps]:=y; close(file_in);
- assign(file_in, progs[prog_stack[ps]]+'.prg'); reset(file_in);
- ln_cnt:=0;
- end;
-
- procedure pop_stack; {Print current filename and list}
- var y: integer; {of newly released variables, then}
- v: boolean; {close current file and open top}
- begin {file in the stack}
- ps:=ps-1;
- if ps>0 then begin
- ln_cnt:=line_stack[ps];
- close(file_in);
- assign(file_in, progs[prog_stack[ps]]+'.prg'); reset(file_in);
- gotoxy(10,20); write('Working on '+progs[prog_stack[ps]]+' ');
- for y:=1 to ln_cnt do readln(file_in, st);
- end;
- end;
-
- function ltrim(var stg: stt): stt; {Remove leading blanks}
- begin
- while (stg[1]=' ') and (length(stg)>0) do stg:=copy(stg,2,length(stg));
- ltrim:=stg;
- end;
-
- function digi_len(ipic: real): integer;
- var uv: integer;
- begin
- uv:=1;
- while ipic/10>1 do begin
- uv:=uv+1; ipic:=ipic/10;
- end;
- digi_len:=uv;
- end;
-
- procedure dbf_header;
- var df, fg, numb_rec, dd1, dd2, dd3: integer;
- ch, field_length, field_type, dec_length: char;
- field_name: string[10];
- up_date: string[8];
- end_header, end_name: boolean;
- procedure get_field;
- begin
- fg:=10; end_name:=false;
- if length(field_name)=0 then fg:=11;
- for df:=1 to fg do begin
- read(file_in,ch); if ord(ch)=0 then end_name:=true;
- if not end_name then field_name:=field_name+ch;
- end;
- end;
-
- procedure f_date;
- var kk: string[2];
- ii: integer;
- begin
- up_date:=''; str(dd2,kk); up_date:=copy(blanks,1,2-length(kk))+kk+'/';
- str(dd3,kk); up_date:=up_date+copy(blanks,1,2-length(kk))+kk+'/';
- str(dd1,kk); up_date:=up_date+kk;
- for ii:=1 to 8 do if up_date[ii]=' ' then up_date[ii]:='0';
- end;
-
- begin
- end_header:=false; numb_rec:=0;
- read(file_in,ch);
- read(file_in,ch); dd1:=ord(ch); read(file_in,ch); dd2:=ord(ch); read(file_in,ch); dd3:=ord(ch);
- read(file_in,ch); numb_rec:=ord(ch); read(file_in,ch); numb_rec:=numb_rec+256*ord(ch);
- write(file_out,copy(blanks,1,17-length(dbf[ps])),'# Records= ',numb_rec,copy(blanks,1,10-digi_len(numb_rec)));
- f_date; writeln(file_out,'Last Updated: ',up_date);
- for df:=1 to 26 do read(file_in,ch); field_name:='';
- while not end_header do begin
- get_field; read(file_in,field_type); for df:=1 to 4 do read(file_in,ch);
- read(file_in,field_length); read(file_in,dec_length); read(file_in,ch);
- while (ord(ch)<>13) and ((ord(ch)<32) or (ord(ch)>127)) do read(file_in,ch);
- if ord(ch)=13 then end_header:=true;
- write(file_out,' ',field_name,copy(blanks,1,12-length(field_name)),field_type,' ',ord(field_length));
- if field_type='N' then writeln(file_out,' ',ord(dec_length)) else writeln(file_out);
- field_name:=ch;
- end;
- end;
-
- procedure ndx_header;
- var df: integer;
- ch: char;
- begin
- write(file_out,' ');
- for df:=1 to 25 do read(file_in,ch);
- while ord(ch)<>0 do begin
- write(file_out,ch); read(file_in,ch);
- end;
- writeln(file_out);
- end;
-
- function get_word(var line: stt): stt; {Put first, and second, in line}
- var word: string[20]; {words in current sentence into}
- begin {This_word and Next_word}
- st:=ltrim(st); word:='';
- while (length(st)>0) and (st[1]<>' ') do begin
- if (st[1]>='a') and (st[1]<='z') then word:=word+upcase(st[1])
- else word:=word+st[1];
- st:=copy(st,2,length(st));
- end;
- get_word:=word;
- end;
-
- function mac(yy: name): boolean;
- var yt: integer;
- begin
- mac:=false;
- for yt:=1 to length(yy) do if yy[yt]='&' then mac:=true;
- end;
-
- procedure parse; {Break sentence up into seperate}
- begin {words to be operated on}
- st:=ltrim(st);
- if length(this_word)>0 then begin
- this_word:=next_word; next_word:=get_word(st); end
- else begin
- this_word:=get_word(st); next_word:=get_word(st);
- end;
- more_words:=false;
- if (length(st)>0) or (length(this_word)>0) then more_words:=true;
- end;
-
- procedure first_char; {Check to see if sentence is}
- begin {a comment or empty}
- skip_line:=false; st:=ltrim(st);
- if (length(st)=0) or (st[1]='*') then skip_line:=true;
- end;
-
- procedure add_mac;
- var s: integer;
- mac_strip: string[15];
- begin
- s:=1; while next_word[s]<>'&' do s:=s+1; mac_strip:=copy(next_word,s+1,length(next_word));
- if mp=0 then begin
- mp:=1; macro[1]:=mac_name; mac_var[1]:=mac_strip;
- end;
- s:=1;
- while (s<=mp) and (mac_name<>macro[s]) do s:=s+1;
- if s>mp then begin
- mp:=mp+1; macro[mp]:=mac_name; mac_var[mp]:=mac_strip;
- end;
- end;
-
- procedure add_dbf;
- var j, e: integer;
- begin
- if mac(next_word) then begin
- mac_name:='d'+next_word; add_mac;
- end
- else begin
- if dp=0 then begin
- dp:=1; dbf[1]:=next_word; dbf_to_ndx[1]:=1; sele_stack[sx]:=1;
- end
- else begin
- j:=1;
- while j<=dp do begin
- if dbf[j]=next_word then begin
- if a_d then sele_stack[sx]:=dbf_to_ndx[j]; j:=dp+5;
- end
- else if next_word<dbf[j] then begin
- dp:=dp+1; e:=dp;
- while e>j do begin
- dbf[e]:=dbf[e-1]; dbf_to_ndx[e]:=dbf_to_ndx[e-1]; e:=e-1;
- end;
- dbf[j]:=next_word;
- if a_d then begin dbf_to_ndx[j]:=dp; sele_stack[sx]:=dp; end
- else dbf_to_ndx[j]:=0;
- end
- else j:=j+1;
- end;
- if j<>dp+5 then begin
- dp:=dp+1; dbf[dp]:=next_word; sele_stack[sx]:=dp; dbf_to_ndx[dp]:=dp;
- end;
- end;
- end;
- end;
-
- procedure add_ndx;
- var j: integer;
- e: integer;
- v: char;
- begin
- while ((this_word<>'TO') and (copy(this_word,1,4)<>'INDE')) and more_words do parse;
- if (this_word='TO') or (copy(this_word,1,4)='INDE') then while length(next_word)>0 do begin
- v:=copy(next_word,length(next_word),1);
- if v=',' then next_word:=copy(next_word,1,length(next_word)-1);
- if mac(next_word) then begin
- mac_name:='x'+next_word; add_mac;
- end
- else begin
- if np=0 then begin
- np:=1; ndx[1]:=next_word; ndx_stack[1]:=sele_stack[sx];
- end
- else begin
- j:=1;
- while j<=np do begin
- if (ndx[j]=next_word) and (sele_stack[sx]=ndx_stack[j]) then j:=np+5
- else if ndx[j]>next_word then begin
- np:=np+1; e:=np; while e>j do begin
- ndx[e]:=ndx[e-1]; ndx_stack[e]:=ndx_stack[e-1]; e:=e-1;
- end;
- ndx[j]:=next_word; ndx_stack[j]:=sele_stack[sx]; j:=np+5;
- end
- else j:=j+1;
- end;
- if j<>np+5 then begin
- np:=np+1; ndx[np]:=next_word; ndx_stack[np]:=sele_stack[sx];
- end;
- end;
- end;
- parse;
- end;
- end;
-
- procedure check_macro;
- var i, j: integer;
- chr: char;
- w2: string[255];
- w1: string[15];
- begin
- w2:='';
- if next_word='=' then begin
- st:=ltrim(st);
- if (st[1]='"') or (ord(st[1])=39) then begin
- chr:=st[1]; st:=copy(st,2,length(st)); j:=1;
- while (st[j]<>chr) and (j<=length(st)) do j:=j+1;
- w2:=copy(st,1,j-1); i:=1;
- while i<=mp do begin
- w1:=copy(macro[i],2,length(macro[i]));
- if this_word=mac_var[i] then begin
- j:=1;
- while (w1[j]<>'&') and (j<=length(w1)) do j:=j+1;
- next_word:=copy(w1,1,j-1)+w2;
- if copy(macro[i],1,1)='d' then add_dbf
- else begin
- this_word:='TO'; st:=''; add_ndx;
- end;
- end;
- i:=i+1;
- end;
- end;
- end;
- end;
-
- procedure what_cmd; {Identify the current dBASE}
- var o: integer; {command and perform the}
- tw, nw: string[4]; {appropriate function}
- begin
- tw:=this_word; nw:=next_word; a_d:=true;
- if pass_one and (all_files='A') then if (tw='DO') then if (nw<>'CASE') and (nw<>'WHIL') then push_stack;
- if pass_one then begin
- if (tw='USE') and (length(nw)>0) then begin
- add_dbf; add_ndx;
- end;
- if (tw='APPE') and (nw='FROM') then begin
- a_d:=false; parse; add_dbf;
- end;
- if ((tw='SET') and (nw='INDE')) or (tw='INDE') then begin
- while (this_word<>'TO') and (more_words) do parse; add_ndx;
- end;
- if (tw='SELE') then begin
- sx:=0; if (length(nw)=1) then sx:=ord(nw)-64;
- if (sx<1) or (sx>10) then sx:=1;
- end;
- end
- else if (tw='STOR') or (nw='=') then check_macro;
- more_words:=false;
- end;
-
- procedure get_line; {Get new sentence and prepare}
- var bb: integer; {for parsing}
- cc: string[3];
- nn: string[255];
- dq: boolean;
- begin
- nn:=''; cc:=''; this_word:=''; next_word:=''; more_words:=true;
- readln(file_in,st); dq:=false;
- for bb:=1 to length(st) do begin
- cc:=st[bb];
- if (cc='"') or (ord(cc)=39) then dq:=true;
- if (cc=',') or ((ord(cc)<31) or (ord(cc)>127)) then cc:=' ';
- if (cc='=') and (not dq) then cc:=' '+cc+' ';
- nn:=nn+cc;
- end;
- st:=nn;
- ln_cnt:=ln_cnt+1; first_char;
- if not skip_line then while more_words begin
- parse; what_cmd;
- end;
- end;
-
- begin {Main Body of the Program}
- get_started; init; pass_one:=true;
- {If abo=Y then the program is to be aborted for some reason}
- if abo<>'Y' then begin
- writeln(file_out,' dBASE III Program Datafile Structure Report for directory '+path);
- write(file_out,'Starting with: '+in_file+'.PRG'+copy(blanks,1,8-length(in_file)));
- writeln(file_out,' run at ',time,' on ',date);
- writeln(file_out);
- outstring:=' ';
- while ps>0 do begin
- while not eof(file_in) do get_line;
- pop_stack;
- end;
-
- pass_one:=false;
- for ps:=1 to sp do begin
- gotoxy(10,20); write('Searching ',progs[ps],' ');
- close(file_in); assign(file_in,progs[ps]+'.prg'); reset(file_in);
- while not eof(file_in) do get_line;
- end;
- for ps:=1 to dp do begin
- write(file_out,dbf[ps]);
- if exist(dbf[ps]+'.dbf') then begin
- close(file_in); assign(file_in,dbf[ps]+'.dbf'); reset(file_in);
- dbf_header;
- end;
- writeln(file_out);writeln(file_out,'*** Index Files ***');
- for sx:=1 to np do if dbf_to_ndx[ps]=ndx_stack[sx] then begin
- write(file_out,ndx[sx]+copy(blanks,1,8-length(ndx[sx])));
- if exist(ndx[sx]+'.ndx') then begin
- close(file_in); assign(file_in,ndx[sx]+'.ndx'); reset(file_in);
- ndx_header;
- end;
- end;
- writeln(file_out); writeln(file_out,'=============================================================');
- writeln(file_out);
- end;
- end;
- close(file_in); close(file_out);
- end.